/**
 * this class handle de CRUD operations in mongo db for Brands
 */
package co.edu.unal.satacredito.database.dao;

import co.edu.unal.satacredito.database.entity.Brand;
import co.edu.unal.satacredito.database.entity.exceptions.NonexistentEntityException;
import co.edu.unal.satacredito.database.entity.exceptions.NullFieldEntityException;
import co.edu.unal.satacredito.database.entity.exceptions.PreexistingEntityException;
import com.google.code.morphia.Datastore;
import com.google.code.morphia.query.Query;
import com.google.code.morphia.query.UpdateOperations;
import java.util.List;
import org.bson.types.ObjectId;

/**
 *
 * @author Miguel Alexander Diaz 257835
 */
public class BrandMongoDao {

    private Datastore ds = null;

    public BrandMongoDao(Datastore ds) {
        this.ds = ds;
        this.ds.ensureIndexes();
    }

    public Datastore getDatastore() {
        return ds;
    }

    public void create(Brand brand) throws PreexistingEntityException {
        try {
            ds.save(brand);
        } catch (Exception e) {
            throw new PreexistingEntityException("The brand with name '"
                    + brand.getBrandName() + "' couldn't be created. Already exist.");
        }
    }

    public void update(ObjectId id, Brand newbrand) throws
            NonexistentEntityException, PreexistingEntityException, NullFieldEntityException, Exception {
        try {
            Query q = ds.createQuery(Brand.class).field("_id").equal(id);
            Query constraint1 = ds.createQuery(Brand.class).field("brandName").equal(newbrand.getBrandName());
            Query constraint2 = ds.createQuery(Brand.class).field("nit").equal(newbrand.getNit());
            if (constraint1.countAll() >= 1) {
                throw new PreexistingEntityException("The brand with name '"
                        + newbrand.getBrandName() + "' couldn't be updated. "
                        + "Already exist a brand with the same key");
            } else if (constraint2.countAll() >= 1) {
                throw new PreexistingEntityException("The brand with nit '"
                        + newbrand.getNit() + "' couldn't be updated. "
                        + "Already exist a brand with the same key");
            } else {
                UpdateOperations<Brand> ops = null;
                try {
                    ops = ds.createUpdateOperations(Brand.class).set("brandName", newbrand.getBrandName()).set("nit", newbrand.getNit()).set("CEOFirstName", newbrand.getCEOFirstName()).set("CEOLastName", newbrand.getCEOLastName()).set("CEODocument", newbrand.getCEODocument()).set("email", newbrand.getEmail()).set("phoneNumber", newbrand.getPhoneNumber()).set("status", newbrand.getStatus());
                } catch (Exception e) {
                    throw new NullFieldEntityException("the Brand with id '"
                            + id.toString() + "' have null fields.");
                }
                ds.update(q, ops);
                //insert here the code for change all status of establishments 
                //asociated to a brand
            }

        } catch (Exception e) {
            if (e.getClass().equals(PreexistingEntityException.class)) {
                throw e;
            } else if (e.getClass().equals(NullFieldEntityException.class)) {
                throw e;
            } else {
                throw new NonexistentEntityException("The brand with id '"
                        + id.toString() + "' couldn't be updated. May no longer exist");
            }
        }

    }

    public void delete(ObjectId id) throws NonexistentEntityException {
        try {
            Query q = ds.createQuery(Brand.class).field("_id").equal(id);
            ds.delete(q);
        } catch (Exception e) {
            throw new NonexistentEntityException("The brand with the id '"
                    + id.toString() + "' couldn't be deleted. May no longer exist.");
        }
    }

    public List<Brand> findAll() throws NonexistentEntityException {
        try {
            List<Brand> list = ds.find(Brand.class).asList();
            return list;
        } catch (Exception e) {
            throw new NonexistentEntityException("The database "
                    + ds.getMongo().getUsedDatabases()
                    + " at " + ds.getMongo().getAddress()
                    + " don't contain any element of the 'Brand' type ");
        }
    }

    public Brand findByBrandName(String brandName) throws NonexistentEntityException, Exception {
        try {
            Query q = ds.createQuery(Brand.class).field("brandName").equal(brandName);
            if (q.countAll() == 0) {
                throw new NonexistentEntityException("The brand with name '"
                        + brandName + "' couldn't be find. May no longer exist");
            } else {
                Brand br = (Brand) q.get();
                return br;
            }
        } catch (Exception e) {
            throw e;
        }
    }

    public Brand findByNit(long nit) throws NonexistentEntityException, Exception {
        try {
            Query q = ds.createQuery(Brand.class).field("nit").equal(nit);
            if (q.countAll() == 0) {
                throw new NonexistentEntityException("The brand with nit '"
                        + nit + "' couldn't be find. May no longer exist");
            } else {
                Brand br = (Brand) q.get();
                return br;
            }
        } catch (Exception e) {
            throw e;
        }
    }

    public Brand findById(ObjectId id) throws NonexistentEntityException, Exception {
        try {
            Query q = ds.createQuery(Brand.class).field("id").equal(id);
            if (q.countAll() == 0) {
                throw new NonexistentEntityException("The brand with id '"
                        + id.toString() + "' couldn't be find. May no longer exist");
            } else {
                Brand br = (Brand) q.get();
                return br;
            }
        } catch (Exception e) {
            throw e;
        }
    }
}